#ifndef __FANTASMA_H__
#define __FANTASMA_H__

#include <iostream>
#include "Posicionable.h"
#include "Movible.h"
#include "MapaDeCeldas.h"
#include <math.h>
#include <SDL_mixer.h>

class Fantasma : public Posicionable{

private:

	Pacman* pacmanOriginal;
	Pacman* pacmanAPerseguir;
	bool escapando;
	bool congelar;

public:

	static const int DIRARRIBA = 3;
	static const int DIRABAJO = 1;
	static const int DIRDERECHA = 0;
	static const int DIRIZQUIERDA = 2;


	int getCeldaX(){
		
		return ((this->getPosX())/this->getPasosPorCelda());
	}

	int getCeldaY(){
		return ((this->getPosY())/this->getPasosPorCelda());
	}

	Fantasma(Pacman* pacman):Posicionable(){
		this->setPasosPorCelda(15);
		this->pacmanAPerseguir = pacman;
		this->pacmanOriginal = pacman;
		this->escapando = false;
		this->congelar = false;
	}

	Fantasma(Pacman* pacman, int x, int y):Posicionable(){
		this->setValorDireccion(0);
		this->setPasosPorCelda(15);
		this->setPosInicialX(x);
		this->setPosInicialY(y);
		this->pacmanAPerseguir = pacman;
		this->pacmanOriginal = pacman;
		this->escapando = false;
		this->congelar = false;
	}

	void actualizarDireccion(MapaDeCeldas* m){
		int nuevaDir = m->getNuevaDireccion(this->getCeldaX(),this->getCeldaY(),this->pacmanAPerseguir->getCeldaX(),this->pacmanAPerseguir->getCeldaY());
		if(this->estaEscapando()){
			switch (nuevaDir){
				case 0: 
					this->setDirAr(m);
					this->setDirAb(m);
					this->setDirIzq(m);
					break;
				case 1: 
					this->setDirDer(m);
					this->setDirIzq(m);
					this->setDirAr(m);
					break;
				case 2: 
					this->setDirAb(m);
					this->setDirAr(m);
					this->setDirDer(m);
					break;
				case 3: 
					this->setDirIzq(m);
					this->setDirDer(m);
					this->setDirAb(m);
					break;
			}
		}
		else{
			this->setDireccion(nuevaDir);
		}
	}
	
	void setDirDer(MapaDeCeldas* m){
		int celdaX = ((this->getPosX()+this->getPasosPorCelda())/this->getPasosPorCelda());
		int celdaY = (this->getPosY()/this->getPasosPorCelda());
		if(m->accederMapaTipo(celdaX,celdaY)>1)
		this->setDireccion(0);
	}

	void setDirAb(MapaDeCeldas* m){
		int celdaX = ((this->getPosX())/this->getPasosPorCelda());
		int celdaY = ((this->getPosY()+this->getPasosPorCelda())/this->getPasosPorCelda());
		if(m->accederMapaTipo(celdaX,celdaY)>1)
		this->setDireccion(1);
	}

	void setDirIzq(MapaDeCeldas* m){
		if(this->getPosX()-1>=0){
		int celdaX = ((this->getPosX()-1)/this->getPasosPorCelda());
		int celdaY = (this->getPosY()/this->getPasosPorCelda());
		if(m->accederMapaTipo(celdaX,celdaY)>1)
		this->setDireccion(2);
		}
	}

	void setDirAr(MapaDeCeldas* m){
		if(this->getPosY()-1>=0){
		int celdaX = ((this->getPosX())/this->getPasosPorCelda());
		int celdaY = ((this->getPosY()-1)/this->getPasosPorCelda());
		if(m->accederMapaTipo(celdaX,celdaY)>1)
		this->setDireccion(3);
		}
	}



//Este seria el equivalente a moverse(MapaDeCelda*)
	void vivir(MapaDeCeldas* m){
		if (!this->congelar) {
			int celdaX;
			int celdaY;
			if(atrapo()){
				if(this->estaEscapando()){
					this->setPosicion(this->getPosXinicial(),this->getPosYinicial());
					this->pacmanAPerseguir->aumentarPuntaje(90);
				}
				else{
					this->pacmanAPerseguir->perderVida();
					
					// Agregado por Sonido
					Mix_Chunk *sonido;
					Mix_OpenAudio(44100, AUDIO_S16, 2, 4096);
					sonido = Mix_LoadWAV("Pacman_MUERTE_WAV_00.01.wav");
					Mix_PlayChannel(-1, sonido, 0);
					// Fin Agregado por Sonido
				}
			}
			if(this->getPosX()%this->getPasosPorCelda()==0 && this->getPosY()% this->getPasosPorCelda()==0)
			actualizarDireccion(m);

			switch(this->getDireccion()){
				case 0:
					celdaX = ((this->getPosX()+this->getPasosPorCelda())/this->getPasosPorCelda());
					celdaY = (this->getPosY()/this->getPasosPorCelda());
					if(m->accederMapaTipo(celdaX,celdaY)>1)
					this->setPosicion(this->getPosX()+1,this->getPosY());
					break;
				case 1:
					celdaX = ((this->getPosX())/this->getPasosPorCelda());
					celdaY = ((this->getPosY()+this->getPasosPorCelda())/this->getPasosPorCelda());
					if(m->accederMapaTipo(celdaX,celdaY)>1)
					this->setPosicion(this->getPosX(),this->getPosY()+1);
					break;
				case 2:
					if(this->getPosX()-1>=0){
					celdaX = ((this->getPosX()-1)/this->getPasosPorCelda());
					celdaY = (this->getPosY()/this->getPasosPorCelda());
					if(m->accederMapaTipo(celdaX,celdaY)>1)
					this->setPosicion(this->getPosX()-1,this->getPosY());
					}
					break;
				case 3:
					if(this->getPosY()-1>=0){
					celdaX = ((this->getPosX())/this->getPasosPorCelda());
					celdaY = ((this->getPosY()-1)/this->getPasosPorCelda());
					if(m->accederMapaTipo(celdaX,celdaY)>1)
					this->setPosicion(this->getPosX(),this->getPosY()-1);
					}
					break;
				}
		}
	}

	void setPacmanAPerseguir(Pacman* p){
		this->pacmanAPerseguir = p;
	}

	bool estaEscapando(){
		return escapando;
	}

	void setEscapando(bool e){
		this->escapando = e;
	}

	bool atrapo(){
		float posFantasmaX = (float)((float)this->pacmanAPerseguir->getPosX()/(float)this->pacmanAPerseguir->getPasosPorCelda());
		float posPacmanX = (float)((float)this->getPosX()/(float)this->getPasosPorCelda());
		float posFantasmaY = (float) ((float)this->pacmanAPerseguir->getPosY()/(float)this->pacmanAPerseguir->getPasosPorCelda());
		float posPacmanY = (float) ((float)this->getPosY()/(float)this->getPasosPorCelda());
		return (abs(posFantasmaX - posPacmanX)<=0.3 && abs(posFantasmaY-posPacmanY)<=0.3);
	}


	/*
	 * Metodo que modifica el pacman a seguir por el fantasma, se utilizara cuando el pacman perseguido coma el 
	 * bonus que realiza esta accion
	 */
	void modificarPerseguido(Pacman* pacman){
		this->pacmanAPerseguir = pacman;		
	}


	void reestablecer(){
		this->pacmanAPerseguir = this->pacmanOriginal;
		this->setEscapando(false);
	}

	~Fantasma() {}

	void congelarFantasma() {
		this->congelar = true;
	}

	void descongelarFantasma() {
		this->congelar = false;
	}

};

#endif